import { useCallback, useEffect, useRef, useState } from 'react';
import type { TypedKey } from '../context/types';
import { globalContext } from '../globalContext';
import { shallowEqual } from '../utils/shallowEqual';

export function useListen<T>(
  key: TypedKey<T>,
): [T, (value: T | ((prev: T) => T)) => void] {
  const [value, setValue] = useState<T>(() => globalContext.getData(key));
  const valueRef = useRef(value);

  useEffect(() => {
    valueRef.current = value;
  }, [value]);

  useEffect(() => {
    const unsubscribe = globalContext.subscribe(key, (newValue: T) => {
      if (!shallowEqual(valueRef.current, newValue)) {
        setValue(newValue);
      }
    });

    return () => {
      unsubscribe();
    };
  }, [key]);

  const set = useCallback(
    (newValue: T | ((prev: T) => T)) => {
      const finalValue =
        typeof newValue === 'function'
          ? (newValue as (prev: T) => T)(globalContext.getData(key))
          : newValue;

      globalContext.setData(key, finalValue);
    },
    [key],
  );

  return [value, set];
}
